// --------------------------------------------------------------------------------------------------------------------
// <copyright file="FileSystemManager.cs" company="GT">
//   Gunther Taborga
// </copyright>
// <summary>
//   Defines the FileSystemManager type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace BatchID3.FileSystem
{
    using System.Collections.Generic;
    using System.IO;

    using BatchID3.FileSystem.Directory;
    using BatchID3.FileSystem.File;
    using BatchID3.FileSystem.Path;

    public class FileSystemManager : IFileSystemManager
    {
        private readonly IDirectoryManager directoryManager;

        private readonly IFileManager fileManager;

        private readonly IPathManager pathManager;

        public FileSystemManager(IDirectoryManager directoryManager, IFileManager fileManager, IPathManager pathManager)
        {
            this.directoryManager = directoryManager;
            this.fileManager = fileManager;
            this.pathManager = pathManager;
        }

        public virtual char DirectorySeparatorChar
        {
            get
            {
                return this.pathManager.DirectorySeparatorChar;
            }
        }

        public virtual string Combine(params string[] paths)
        {
            return this.pathManager.Combine(paths);
        }

        public void CreateDirectory(string path)
        {
            this.directoryManager.CreateDirectory(path);
        }

        public void DeleteDirectory(string path, bool recursive)
        {
            this.directoryManager.DeleteDirectory(path, recursive);
        }

        public void DeleteFile(string path)
        {
            this.fileManager.DeleteFile(path);
        }

        public bool DirectoryExists(string path)
        {
            return this.directoryManager.DirectoryExists(path);
        }

        public bool FileExists(string path)
        {
            return this.fileManager.FileExists(path);
        }

        public string GetActualPath(string path)
        {
            if (!(this.fileManager.FileExists(path) || this.directoryManager.DirectoryExists(path)))
            {
                return path;
            }

            var directoryInfo = new DirectoryInfo(path);

            return directoryInfo.Parent != null
                    ? this.GetActualPath(directoryInfo)
                    : directoryInfo.Name.ToUpper();
        }

        public IEnumerable<string> GetDirectories(string path)
        {
            return this.directoryManager.GetDirectories(path);
        }

        public IEnumerable<string> GetDirectories(string path, string searchPattern, SearchOption searchOption = SearchOption.TopDirectoryOnly)
        {
            return this.directoryManager.GetDirectories(path, searchPattern, searchOption);
        }

        public string GetDirectoryName(string path)
        {
            return this.pathManager.GetDirectoryName(path);
        }

        public string GetFileName(string path)
        {
            return this.pathManager.GetFileName(path);
        }

        public IEnumerable<string> GetFiles(string path, string searchPattern, SearchOption searchOption = SearchOption.TopDirectoryOnly)
        {
            return this.directoryManager.GetFiles(path, searchPattern, searchOption);
        }

        public char[] GetInvalidFileNameChars()
        {
            return this.pathManager.GetInvalidFileNameChars();
        }

        public char[] GetInvalidPathChars()
        {
            return this.pathManager.GetInvalidPathChars();
        }

        public DirectoryInfo GetParent(string path)
        {
            return this.directoryManager.GetParent(path);
        }

        public void MoveFile(string sourceFileName, string destinationFileName)
        {
            this.fileManager.MoveFile(sourceFileName, destinationFileName);
        }

        private string GetActualPath(DirectoryInfo directoryInfo)
        {
            return this.pathManager.Combine(
                this.GetActualPath(directoryInfo.Parent.FullName),
                directoryInfo.Parent.GetFileSystemInfos(directoryInfo.Name)[0].Name);
        }
    }
}